#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/wait.h>
#include<errno.h>
#include<stdlib.h>

#define SIZE 256
#define ZERO '\0'
#define NUM 32
#define SEP " "

const char* GetUser()
{
  const char* user=getenv("USER");
  if(user==NULL) return "None";
  return user;
}

const char* GetHostName()
{
  const char* hostname=getenv("HOSTNAME");
  if(hostname==NULL) return "None";
  return hostname;
}

const char* GetCwd()
{
  const char* cwd=getenv("PWD");
  if(cwd==NULL) return "None";
  return cwd;
}

void GetCwd2(const char** p)
{
  (*p)+=strlen(*p)-1;//指向最后一个字符
  while(**p!='/') (*p)--;
}

void MakeCommandLine()
{
  char commandline[SIZE];
  const char* user=GetUser();
  const char* hostname=GetHostName();
  const char* cwd=GetCwd();

  GetCwd2(&cwd);
  snprintf(commandline,sizeof(commandline),"[%s@%s %s]> ",user,hostname,strlen(cwd)==1?"/":cwd+1);
  printf("%s",commandline);
  fflush(stdout);
}


int GetUserCommand(char* usercommand,size_t size)
{
  char* ret=fgets(usercommand,size,stdin);
  if(ret==NULL) return -1;
  usercommand[strlen(usercommand)-1]=ZERO;
  return strlen(usercommand);
}

char* gArgv[NUM];


void SplitCommand(char usercommand[])
{
  gArgv[0]=strtok(usercommand,SEP);
  int i=1;
  while((gArgv[i++]=strtok(NULL,SEP)));
}

void Die()
{
  exit(1);
}


int lastcode=0;

void ExecuteCommand()
{
  pid_t id=fork();
  if(id==-1) Die();
  else if(id==0)
  {
    //child
    execvp(gArgv[0],gArgv);
    exit(errno);
  }
  else
  {
    //parent
    int status=0;
    pid_t rid=waitpid(id,&status,0);
    if(rid>0)
    {
      //等待成功
      lastcode=WEXITSTATUS(status);
      if(lastcode!=0)
      {
        printf("%s:%s %d\n",gArgv[0],strerror(lastcode),lastcode);
      }
    }
  }
}

char cwd[SIZE*2];

void Cd()
{
  char* path=gArgv[1];
  if(path==NULL) path=getenv("HOME");
  chdir(path);

  //char cwd[SIZE*2];
  char tmp[SIZE*2];
  getcwd(tmp,sizeof(tmp));
  snprintf(cwd,sizeof(cwd),"PWD=%s",tmp);
  putenv(cwd);
}


int CheckBulidin()
{
  int ret=0;
  if(strcmp(gArgv[0],"cd")==0)
  {
    ret=1;
    Cd();
  }
  else if(strcmp(gArgv[0],"echo")==0&&strcmp(gArgv[1],"$?")==0)
  {
    ret=1;
    printf("%d\n",lastcode);
    lastcode=0;
  }
  return ret;
}


int main()
{
  int quit=0;
  while(!quit)
  {
    //1.我们需要自己输出一个命令行
    MakeCommandLine();

    //2.获取用户命令字符串
    char usercommand[SIZE];
    int n=GetUserCommand(usercommand,sizeof(usercommand));
    (void)n;

    //3.命令行字符串分割
    SplitCommand(usercommand);

    //4.检测命令是否为内建命令
    int ret=CheckBulidin();
    if(ret)
      continue;

    //4.执行命令
    ExecuteCommand();
  }

  return 0;
}
